package com.itheima.app.manager;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.huanxin.HuanXinTemplate;
import com.itheima.domain.db.Question;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Friend;
import com.itheima.domain.mongo.RecommendUser;
import com.itheima.domain.mongo.Sound;
import com.itheima.domain.mongo.Visitor;
import com.itheima.service.db.QuestionService;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.FriendService;
import com.itheima.service.mongo.RecommendUserService;
import com.itheima.service.mongo.UserLocationService;
import com.itheima.service.mongo.VisitorService;
import com.itheima.util.ConstantUtil;
import com.itheima.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class MakeFriendManager {

    @Reference
    private RecommendUserService  recommendUserService;
    @Reference
    private UserInfoService userInfoService;
    @Reference
    private QuestionService questionService;
    @Reference
    private VisitorService visitorService;
    @Reference
    private UserLocationService userLocationService;
    @Reference
    private FriendService friendService;
    @Autowired
    private FastFileStorageClient client;
    @Autowired
    private FdfsWebServer webServer;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    //今日佳人
    public RecommendUserVo findTodayBest() {
        //1.获取登录用户id
        Long userId = UserHolder.get().getId();

        //2.根据id查询佳人
        RecommendUser recommendUser = recommendUserService.findTodayBest(userId);

        //3.根据推荐给我的佳人id查询其userInfo
            //先判断查询返回的recommendUser是否为空,如果是空,手动推荐一个(企业中是没有这步骤的)
        if(recommendUser==null){
            recommendUser = new RecommendUser();
            recommendUser.setUserId(1L);
            recommendUser.setScore(99D);
        }

        //4.组装返回Vo
        RecommendUserVo recommendUserVo = new RecommendUserVo();
        recommendUserVo.setUserInfo(userInfoService.findByUserId(recommendUser.getUserId()));
        recommendUserVo.setFateValue(recommendUser.getScore().longValue());
        return recommendUserVo;
    }

    //推荐用户列表
    public PageBeanVo findRecommendUserList(Integer pageNum, Integer pageSize) {
        //1.获取登录用户
        Long userId = UserHolder.get().getId();

        //2.根据登录用户id分页获取其推荐用户列表
        PageBeanVo pageBeanVo = recommendUserService.findRecommendUserList(userId,pageNum,pageSize);

        //3.模拟数据
        List<RecommendUser> recommendUserList = (List<RecommendUser>) pageBeanVo.getItems();
        if(CollectionUtil.isEmpty(recommendUserList)){
            for (Integer i = 1; i < 10; i++) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(i.longValue());
                recommendUser.setScore(98D);
                recommendUserList.add(recommendUser);
            }
        }
        
        //4.组装Vo  :  RecommendUser------>RecommendUserVo
        List<RecommendUserVo> recommendUserVoList = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUserList) {
            //创建一个RecommendUserVo设置数据
            RecommendUserVo recommendUserVo = new RecommendUserVo();

            recommendUserVo.setUserInfo(userInfoService.findByUserId(recommendUser.getUserId()));
            recommendUserVo.setFateValue(recommendUser.getScore().longValue());

            recommendUserVoList.add(recommendUserVo);
        }

        pageBeanVo.setItems(recommendUserVoList);
        return pageBeanVo;
    }

    //推荐用户详细信息(单人)
    public RecommendUserVo findRecommendUserInfo(Long recommendId) {
        //1.查询佳人信息详情
        UserInfo userInfo = userInfoService.findByUserId(recommendId);

        //2.根据两人id调用service查询推荐用户信息
        Long userId = UserHolder.get().getId();
        RecommendUser recommendUser = recommendUserService.findRecommendUser(userId,recommendId);

        //3.如果查不到，给默认值(设置缘分值)
        Long fateValue = 99L;
        if(recommendUser != null){
            //查到了
            fateValue = recommendUser.getScore().longValue();
        }

        //4.返回Vo
        RecommendUserVo recommendUserVo = new RecommendUserVo();
        recommendUserVo.setUserInfo(userInfo);
        recommendUserVo.setFateValue(fateValue);

        return recommendUserVo;

    }

    //聊一下 -- 查看陌生人问题
    public String findStrangerQuestion(Long userId) {
        //1.查询他设置的陌生人问题
        Question question = questionService.findByUserId(userId);

        //2. 如果查不到,返回默认值
        if (question == null){
            return new SettingVo().getStrangerQuestion();
        }

        //3.返回问题
        return  question.getStrangerQuestion();
    }

    //最近访客(谁看过我)
    public List<VisitorVo> findVisitorList() {
        //1.获取登录用户id
        Long userId = UserHolder.get().getId();

        //2.从redis中获取当前用户最后一次访问时间,如果时间为空,设置为当前时间
        String time = stringRedisTemplate.opsForValue().get(ConstantUtil.LAST_ACCESS_TIME + userId);
        if(StringUtils.isEmpty(time)){
            time=System.currentTimeMillis()+"";
        }

        //3.根据userId和lastAccessTime调用service查询
        List<Visitor> visitorList =  visitorService.findVisitorList(userId,time);

        //4.封装返回结果
        List<VisitorVo> visitorVoList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(visitorList)){
            VisitorVo visitorVo = new VisitorVo();
            for (Visitor visitor : visitorList) {
                //设置来访用户的信息，注意findByUserId的参数是来访用户的id
                visitorVo.setUserInfo(userInfoService.findByUserId(visitor.getVisitorUserId()));

                visitorVo.setFateValue(99L);
                visitorVoList.add(visitorVo);
            }
        }

        //5.更新一下最后一次访问时间
        stringRedisTemplate.opsForValue().set(ConstantUtil.LAST_ACCESS_TIME + userId,System.currentTimeMillis()+"");

        return  visitorVoList;
    }

    //上报地理位置
    public void saveUserLocation(Double latitude, Double longitude, String addrStr) {

        //1.获取用户id
        Long userId = UserHolder.get().getId();

        //2.调用service保存
        userLocationService.saveUserLocation(userId,latitude,longitude,addrStr);
    }

    //搜索附近的人
    public List<NearUserVo> findNearUserList(String gender, Long distance) {
        //1.获取登录用户id
        Long userId = UserHolder.get().getId();

        //2. 根据登录用户位置和指定长度寻找附近的人
        List<Long> userIdList = userLocationService.findNearUserList(userId,distance);

        //3.如果没查到附近的人,直接返回空集合
        if (CollectionUtil.isEmpty(userIdList)){
            return new ArrayList<NearUserVo>();
        }
        List<NearUserVo> nearUserVoList = new ArrayList<>();
        //4. 如果查到了
        for (Long uid : userIdList) {
            //4-1. 先排除自己
            if (uid == userId){
                continue;
            }

            //4-2.筛选性别(man )
            UserInfo userInfo = userInfoService.findByUserId(uid);
            if (!StringUtils.equals(userInfo.getGender(),gender)){
                continue;
            }

            //4-3 将符合条件的用户组装成返回对象
            NearUserVo nearUserVo = new NearUserVo();
            nearUserVo.setUserId(uid);
            nearUserVo.setAvatar(userInfo.getAvatar());
            nearUserVo.setNickname(userInfo.getNickname());
            nearUserVoList.add(nearUserVo);

        }
        return nearUserVoList;
    }

    //打招呼
    public void replyStrangerQuestion(Integer strangeId, String reply) {
        //1.获取登录用户id
        Long userId = UserHolder.get().getId();

        //2.根据id查询用户信息中的nickname
        String nickname = userInfoService.findByUserId(userId).getNickname();

        //3.查询佳人设置的问题
            //没有设置问题的话，直接拿默认值
        String strangerQuestion=new SettingVo().getStrangerQuestion();
        Question question = questionService.findByUserId(strangeId.longValue());
        if(question != null){
            //设置问题了，从question表中根据用户id取出问题
            strangerQuestion = question.getStrangerQuestion();
        }

        //4.拼接json串
        Map<String, String> map = new HashMap<>();
        map.put("userId",userId+"");
        map.put("nickname",nickname);
        map.put("strangerQuestion",strangerQuestion);
        map.put("reply",reply);
        String json = JSON.toJSONString(map);
        System.out.println("我发送的json内容是："+json);

        //5.调用环信的api发送出去
        huanXinTemplate.sendMsg(strangeId+"",json);
    }

    //添加好友(聊一下)
    public void saveFriend(long friendId) {
        //1.获取登录用户id
        Long userId = UserHolder.get().getId();

        //2.调用service在mongo中保存好友关系
        friendService.save(userId,friendId);

        //3.调用api在环信中保存好友关系
        huanXinTemplate.addContacts(userId,friendId);
    }

    //查询我的好友
    public PageBeanVo findMyFriend(Integer pageNum, Integer pageSize) {
        //1.获取登录用户id
        Long userId = UserHolder.get().getId();

        //2.根据id调用service分页查询好友列表
        PageBeanVo pageBeanVo = friendService.findFriendById(userId,pageNum,pageSize);

        //3.组装Vo
        List<Friend> friendList = (List<Friend>) pageBeanVo.getItems();
        List<ContactVo> contactVoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(friendList)){
            for (Friend friend : friendList) {

                ContactVo contactVo = new ContactVo();
                //好友id
                Long friendId = friend.getFriendId();
                //将好友信息存入好友类(前端)中
                contactVo.setUserInfo(userInfoService.findByUserId(friendId));
                //这里有个坑，contactVo的userId是String类型，要手动封装
                contactVo.setUserId(friendId+"");
                contactVoList.add(contactVo);
            }
        }
        //把封装好返回给前端的list放入
        pageBeanVo.setItems(contactVoList);
        return pageBeanVo;
    }
    //桃花传音-发送语音（学生实战）
    public void setVoice(MultipartFile soundFile) throws IOException {
        Long userId = UserHolder.get().getId();
        //规定用户一天只能发送 10条
        //采用技术是  使用redis存储相关信息 、每日凌晨开始清理redis为新的一天准备
        if (!stringRedisTemplate.hasKey(ConstantUtil.VOICE_USER_SET_TIME+userId)){
            //不存在 保存信息  并设置初值为 每日的数量  10  并设置1天时间过期
            stringRedisTemplate.opsForValue().set(ConstantUtil.VOICE_USER_SET_TIME+userId,ConstantUtil.VOICE_TIME.toString(), Duration.ofDays(1));
            System.out.println(ConstantUtil.VOICE_TIME+"用户剩余次数");
        }else{
            //存在----查询次数
            int time = Integer.parseInt(stringRedisTemplate.opsForValue().get(ConstantUtil.VOICE_USER_SET_TIME+userId));
            if (time>0){
                //次数大于零   递减操作
                System.out.println((time-1)+"这是剩余次数");
                stringRedisTemplate.opsForValue().decrement(ConstantUtil.VOICE_USER_SET_TIME+userId);
            }else{
                //次数为零 不允许操作
                throw  new RuntimeException("没有次数了");
            }
        }

        //todo 语音 审核

        //保存到  fastDfs上
        InputStream fis = soundFile.getInputStream();
        StorePath storePath = client.uploadFile(fis, soundFile.getSize(), FileUtil.extName(soundFile.getOriginalFilename()), null);
        //将路径存储
        String path = webServer.getWebServerUrl() + storePath.getFullPath();

        Sound sound = new Sound();
        sound.setSoundUrl(path);
        sound.setUserId(userId);
        //保存用户的语音信息
        friendService.saveVoice(sound);
    }
    //桃花传音-接收语音（学生实战）
    public SoundVo getVoice() {
        Long userId = UserHolder.get().getId();
        //查询redis中的次数
        int time;//表示剩余次数
        SoundVo soundVo = new SoundVo();
        soundVo.setNickname("");
        soundVo.setRemainingTimes(0);
        if (!stringRedisTemplate.hasKey(ConstantUtil.VOICE_USER_GET_TIME+userId)){
            //不存在  存入剩余次数并返回
            stringRedisTemplate.opsForValue().set(ConstantUtil.VOICE_USER_GET_TIME+userId,ConstantUtil.VOICE_USER_TIME.toString(),Duration.ofDays(1));
           //time表示剩余次数  这次
            time=ConstantUtil.VOICE_USER_TIME;
        }else {
            //存在查询次数 是不是大于零
            String s = stringRedisTemplate.opsForValue().get(ConstantUtil.VOICE_USER_GET_TIME + userId);
            time = Integer.parseInt(s);
            if (time>0){
                //大于零    次数减一保存   返回前端与redis
                Long decrement = stringRedisTemplate.opsForValue().decrement(ConstantUtil.VOICE_USER_GET_TIME + userId);
                time--;
                System.out.println(time+"-----还有几次数");
            }else{
                //没有次数了
                System.out.println("没有次数了");
                return soundVo;
            }
        }
        //1 拿到返回的语音信息、[ 业务需求--每条语音 只能被一人收听、所以需要每次都去查询数据库防止 一条语音被多次收听 ]
        Sound sound=  friendService.getVoice(userId);

        if (sound!=null){
            //2 查询用户详情
            UserInfo userInfo = userInfoService.findByUserId(sound.getUserId());
            //3 封装vo返回数据
            BeanUtil.copyProperties(userInfo,soundVo);
            soundVo.setSoundUrl(sound.getSoundUrl());
            soundVo.setRemainingTimes(time);
            return soundVo;
        }
        if (sound==null&& time!=0){
            soundVo.setRemainingTimes(time);
            return soundVo;
        }
        return soundVo;
    }
}

